﻿using DTM.Core.Exceptions;
using DTM.Core.Utils;
using DTM.Repository;
using FluentValidation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DTM.Domain
{
    /// <summary>
    /// Class <see cref="ServiceBase" /> define base service class
    /// </summary>
    /// <typeparam name="T">The type of the validator.</typeparam>
    public abstract class ServiceBase<T> : IServiceBase<T>
        where T : class
    {
        #region Fields

        private readonly IUnitOfWorkProvider _unitOfWorks;
        private readonly IValidator<T> _validator;

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Class <see cref="UserService" /> constructor
        /// </summary>
        /// <param name="unitOfWorks">The unit of works.</param>
        /// <param name="validator">The validator.</param>
        /// <exception cref="ArgumentNullException">
        /// unitOfWorkProvider
        /// or
        /// validator
        /// </exception>
        public ServiceBase(IUnitOfWorkProvider unitOfWorks, IValidator<T> validator)
        {
            Core.Utils.Validate.NotNull<ArgumentNullException>(unitOfWorks, "unitOfWorks");
            Core.Utils.Validate.NotNull<ArgumentNullException>(validator, "validator");

            _validator = validator;
            _unitOfWorks = unitOfWorks;
        }

        #endregion Constructors

        #region Methods

        /// <summary>
        /// Validates the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <returns>True if not null and valid</returns>
        public bool IsValid(T entity)
        {
            if (entity == null)
            {
                return false;
            }
            var result = _validator.Validate(entity);
            return result.IsValid;
        }

        /// <summary>
        /// Gets the read-only unit of work.
        /// </summary>
        /// <returns></returns>
        protected IUnitOfWork GetUnitOfWork()
        {
            var unitOfWork = _unitOfWorks.GetUnitOfWork();
            if (unitOfWork == null)
            {
                throw new ArgumentNullException("Unit of work");
            }
            return unitOfWork;
        }

        /// <summary>
        /// Validates the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        protected void Validate(T entity)
        {
            var result = _validator.Validate(entity);
            if (!result.IsValid)
            {
                throw new CustomValidationException(result.Errors);
            }
        }

        #endregion Methods
    }
}